

#include "bthapi.h"




////////////////////////////////////////////


//
// paraseBlobToRecs - use isDpStream object to parse the response
// from the sdp server.s
//
HRESULT ParseBlobToRecs(UCHAR *pbData, DWORD cbStream, ISdpRecord ***pppSdpRecords, ULONG *pcbRec)
{
	HRESULT hr;
	ULONG ulError;
	ISdpStream *pIStream = NULL;
	*pppSdpRecords = NULL;
	*pcbRec = 0;

	hr = CoCreateInstance(__uuidof(SdpStream), NULL, CLSCTX_INPROC_SERVER, __uuidof(ISdpStream), (LPVOID *)&pIStream);
	if (FAILED(hr)) return hr;
	//validate sdp data blob
	hr = pIStream->Validate(pbData, cbStream, &ulError);

	if (SUCCEEDED(hr))
	{
		hr = pIStream->VerifySequenceOf(pbData, cbStream, SDP_TYPE_SEQUENCE, NULL, pcbRec);
		if (SUCCEEDED(hr) && *pcbRec > 0)
		{
			*pppSdpRecords = (ISdpRecord**)CoTaskMemAlloc(sizeof(ISdpRecord*)*(*pcbRec));
			if (pppSdpRecords!=NULL)
			{
				hr = pIStream->RetrieveRecords(pbData, cbStream, *pppSdpRecords, pcbRec);
				if (!SUCCEEDED(hr))
				{
					CoTaskMemFree(*pppSdpRecords);
					*pppSdpRecords = NULL;
					*pcbRec = 0;
				}
			} else
			{
				hr = E_OUTOFMEMORY;
			}
		}
	}

	if (pIStream!=NULL)
	{
		pIStream->Release();
		pIStream = NULL;
	}
	return hr;

}




int MYBUFSIZE = 16384;

int QueryServiceBtDevList(HWND hWnd, BT_ADDR bta, GUID *pguid)
{
	DWORD dwFlags, dwLen;
	HANDLE hLookup;
	TCHAR szDeviceName[256];
	LPWSAQUERYSET pQuerySet;
	PBYTE pQuery;
	int i, rc;


	pQuery = (PBYTE)LocalAlloc(LPTR, MYBUFSIZE);
	if (!pQuery) return 0;

	pQuerySet = (LPWSAQUERYSET)pQuery;
	memset(pQuery, 0, MYBUFSIZE);
	pQuerySet->dwSize = sizeof(WSAQUERYSET);
	pQuerySet->dwNameSpace = NS_BTH;

	//specify device
	CSADDR_INFO csi;
	memset(&csi, 0, sizeof(csi));

	SOCKADDR_BTH sa;
	memset(&sa, 0, sizeof(sa));
	sa.btAddr = bta;
	sa.addressFamily = AF_BT;

	//specify the remote device address
	csi.RemoteAddr.lpSockaddr = (LPSOCKADDR)&sa;
	csi.RemoteAddr.iSockaddrLength = sizeof(SOCKADDR_BTH);
	pQuerySet->lpcsaBuffer = &csi;
	pQuerySet->dwNumberOfCsAddrs = 1;

	//from query based on service class being checked
	BTHNS_RESTRICTIONBLOB btrblb;
	memset(&btrblb, 0, sizeof(btrblb));
	btrblb.type = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
	btrblb.numRange = 1;
	btrblb.pRange[0].minAttribute = 0;
	btrblb.pRange[0].maxAttribute = 0xffff;
	btrblb.uuids[0].uuidType = SDP_ST_UINT128;    //define search type
	memcpy(&btrblb.uuids[0].u.uuid128, pguid, sizeof(GUID));

	//create blob to point to restriction blob
	BLOB blob;
	blob.cbSize = sizeof(BTHNS_RESTRICTIONBLOB);
	blob.pBlobData = (PBYTE)&btrblb;
	pQuerySet->lpBlob = &blob;
	dwFlags = 0;

	rc = WSALookupServiceBegin(pQuerySet, dwFlags, &hLookup);
	if (rc) return rc;

	//setup query set for serviceNext call
	pQuerySet->dwNumberOfCsAddrs = 1;
	pQuerySet->lpszServiceInstanceName = szDeviceName;
	memset(szDeviceName, 0, sizeof(szDeviceName));

	dwFlags = LUP_RETURN_NAME | LUP_RETURN_ADDR;
	dwLen = MYBUFSIZE;
	while((rc = WSALookupServiceNext(hLookup, dwFlags, &dwLen, pQuerySet)) == 0) 
	{
		ISdpRecord **pRecordArg;
		int cRecordArg = 0;

		//setup attribute query
		HRESULT hr = ParseBlobToRecs (pQuerySet->lpBlob->pBlobData, pQuerySet->lpBlob->cbSize, &pRecordArg, (ULONG *)&cRecordArg);
		if (hr == ERROR_SUCCESS)
		{
			for (i = 0; i < cRecordArg; i++)
			{
				pRecordArg[i]->Release();
			}
			CoTaskMemFree(pRecordArg);
		}
		dwLen = MYBUFSIZE;
		i++;
	}
	rc = WSALookupServiceEnd(hLookup);
	LocalFree(pQuery);
	return rc;
}







BOOL GetBT_ADDR(LPWSTR pszAddress, BT_ADDR *paddr) 
{
	// Bump pointer through any leading spaces
	int i;
	WCHAR szAddress[20], *pTemp;

	memset(szAddress, 0, sizeof(szAddress));
	wcsncpy(szAddress, pszAddress, 2);
	wcsncpy(szAddress + 2, pszAddress + 3, 2);
	wcsncpy(szAddress + 4, pszAddress + 6, 2);
	wcsncpy(szAddress + 6, pszAddress + 9, 2);
	wcsncpy(szAddress + 8, pszAddress + 12, 2);
	wcsncpy(szAddress + 10, pszAddress + 15, 2);
	pTemp = szAddress;

	for (i = 0 ; i < 4 ; ++i, ++pTemp) 
	{
		if (!iswxdigit (*pTemp))
			return(false);

		int c = *pTemp;
		if (c >= 'a')
			c = c - 'a' + 0xa;
		else if (c >= 'A')
			c = c - 'A' + 0xa;
		else c = c - '0';

		if ((c < 0) || (c > 16))
			return(false);

		*paddr = *paddr * 16 + c;
	}

	for (i = 0; i < 8 ; ++i, ++pTemp) 
	{
		if (!iswxdigit (*pTemp))
			return(false);

		int c = *pTemp;
		if (c >= 'a')
			c = c - 'a' + 0xa;
		else if (c >= 'A')
			c = c - 'A' + 0xa;
		else c = c - '0';

		if ((c < 0) || (c > 16))
			return(false);

		*paddr = *paddr * 16 + c;
	}

	if ((*pTemp != ' ') && (*pTemp != '\0'))
		return(false);
	else
		return(true);
}
